package se.kayarr.cardplay.gameplay;

import java.util.HashMap;
import java.util.Map;

import se.kayarr.cardplay.exceptions.SessionInProgressException;

import lombok.Getter;

public enum Type {
	NEUTRAL		("Neutral"),
	
	BLAZE		("Blaze"),
	AQUA		("Aqua"),
	ELECTRO		("Electro"),
	VEGETATION	("Vegetation"),
	
	KINETIC		("Kinetic"),
	PSYCHIC		("Psychic"),
	ASTRAL		("Astral");
	
	private static Map<TypePair, Double> damageMultiplierMap = new HashMap<>();
	
	private static void damageMult(Type attacker, Type target, double multiplier) {
		damageMultiplierMap.put(new TypePair(attacker, target), multiplier);
	}
	
	static {
		try {
			setupDamageMults();
		}
		catch (SessionInProgressException e) {}
	}
	
	public static void setupDamageMults() throws SessionInProgressException {
		if(Session.getCurrentSession() != null) throw new SessionInProgressException();
		
		damageMultiplierMap.clear();
		
		//Default multiplier is 1.0
		damageMult(AQUA, BLAZE, 1.8);
		damageMult(AQUA, ELECTRO, 1.8);
		damageMult(AQUA, VEGETATION, 0.2);
		
		damageMult(BLAZE, KINETIC, 1.8);
		damageMult(BLAZE, VEGETATION, 2.0);
		damageMult(BLAZE, AQUA, 0.2);
		
		damageMult(ELECTRO, AQUA, 1.7);
		damageMult(ELECTRO, PSYCHIC, 1.1);
		damageMult(ELECTRO, KINETIC, 0.2);
		
		damageMult(ASTRAL, ASTRAL, 2.2);
		damageMult(ASTRAL, NEUTRAL, 0.6);
		damageMult(ASTRAL, PSYCHIC, 1.6);
		
		damageMult(KINETIC, KINETIC, 1.4);
		damageMult(KINETIC, ASTRAL, 1.6);
		
		damageMult(PSYCHIC, PSYCHIC, 1.6);
		damageMult(PSYCHIC, KINETIC, 1.6);
	}
	
	public static double getDamageMultiplier(Type attacker, Type target) {
		TypePair pair = new TypePair(attacker, target);
		
		if(!damageMultiplierMap.containsKey(pair)) return 1.0; //No particular multiplier
		return damageMultiplierMap.get(pair);
	}
	
	@Getter private String name;
	
	private Type(String name) {
		this.name = name;
	}
	
	public String toString() {
		return name;
	}
	
	private static class TypePair {
		@Getter private Type attacker;
		@Getter private Type target;
		
		public TypePair(Type attacker, Type target) {
			this.attacker = attacker;
			this.target = target;
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result
					+ ((attacker == null) ? 0 : attacker.hashCode());
			result = prime * result
					+ ((target == null) ? 0 : target.hashCode());
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			TypePair other = (TypePair) obj;
			if (attacker != other.attacker)
				return false;
			if (target != other.target)
				return false;
			return true;
		}
	}
}
